package org.springframework.samples.webflow.dao;

import java.util.Collection;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.samples.webflow.entity.Category;
import org.springframework.samples.webflow.entity.Customer;
import org.springframework.samples.webflow.entity.Product;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@SuppressWarnings("unchecked")
@Service
@Transactional
public class CommonDaoImpl implements CommonDao {

	@PersistenceContext
	private EntityManager entityManager;
	
	@Override
	public Collection<Customer> getAll() {
    	Query query = entityManager.createQuery("from Customer");
        return query.getResultList();
    }
    
	@Override
	public Collection<Customer> findByCriterias(SearchCriteria searchCriteria) {
		StringBuilder searchQuery = new StringBuilder(512);
		searchQuery.append("from Customer as c");
		
        boolean firstParam = true;
		for (String paramName : searchCriteria.getCriterias().keySet()) {
			System.out.println("findByCriterias: " + paramName + ":" + searchCriteria.getCriterias().get(paramName).getValue());
			if (firstParam) {
				searchQuery.append(" where");
			}
			searchQuery.append(" ");
			searchQuery.append(paramName);
			searchQuery.append(searchCriteria.getCriterias().get(paramName).getOperator().getExpresion());
			searchQuery.append(":");
			searchQuery.append(paramName);
		}
		Query query = entityManager.createQuery("from Customer as c where lower(c.name) like lower(:name)");
		for (String paramName : searchCriteria.getCriterias().keySet()) {
			switch (searchCriteria.getCriterias().get(paramName).getOperator()) {
			case LIKE :
				query.setParameter(paramName, "%" + searchCriteria.getCriterias().get(paramName).getValue() + "%");
				break;
			default :
				query.setParameter(paramName, searchCriteria.getCriterias().get(paramName).getValue());
			}
		}
		Collection<Customer> result = query.getResultList();
		System.out.println("findByCriterias result size:" + result.size());
		return result;
    }
	
	@Override
    public Collection<Customer> findByName(String name) {
    	Query query = entityManager.createQuery("from Customer as c where lower(c.name) like lower(:name)");
    	query.setParameter("name", "%"+ name + "%");
        return query.getResultList();
    }

	@Override
    public Customer getById(Long id) {
        return entityManager.find(Customer.class, id);
    }

	@Override
    public void save(Customer customer) {
    	entityManager.persist(customer);
    }

	@Override
    public void delete(Long id) {
    	Customer customer = entityManager.find(Customer.class, id);  
    	entityManager.remove(customer);
    }

	@Override
	public Collection<Category> getAllCategories() {
		Query query = entityManager.createQuery("from Category");
        return query.getResultList();
	}

	@Override
	public void saveCategory(Category category) {
		entityManager.persist(category);
	}

	@Override
	public Collection<Product> getProductsByCategory(Long categoryId) {
		Query query = entityManager.createQuery("from Product as p where p.category.categoryId = :categoryId");
    	query.setParameter("categoryId", categoryId);
        return query.getResultList();
	}

	@Override
	public void saveProduct(Product product) {
		entityManager.persist(product);
	}

	@Override
	public Product getProductById(Long productId) {
		return entityManager.find(Product.class, productId);
	}
}
